iT邦幫忙

2023 iThome 鐵人賽

DAY 21
0
Software Development

Laravel 後端菜鳥可以知道的流程概念系列 第 21

Laravel Mutator & Accessor / 修改取得圖片路徑的方式

  • 分享至 

  • xImage
  •  

昨天我在圖片上傳功能的時候,讓圖片路徑存入資料庫,但是在資料取出時,圖片路徑要轉變為前端可以讀取的網址,需要程式進一步處理

  • 存入資料庫的圖片路徑

    https://ithelp.ithome.com.tw/upload/images/20231006/20162893bnQsoxcX1f.png

  • 在前端畫面中顯示的路徑

    //controller
    public function create(Group $group)
    {
    		$group['image_path'] = Storage::url($group['image_path']);
    				// 將路徑用 Storage::url() 轉換為前端可讀取的位置
    				// dd()結果如圖
    		return view('group.createProduct', [
    				'group' => $group,
    
    		]);
    }
    

    https://ithelp.ithome.com.tw/upload/images/20231006/20162893oa89hNihnR.png

為了解決這類問題, Laravel 有 Mutator 及 Accessor 功能,可以針對資料在存進資料庫及取出資料庫的時候,進行資料的處理,可能包含格式轉換或回傳自定義的內容。

純後端如何解決這件事情?

純後端工程師在處理回傳資料的轉換時,可以直接透過 Resource Collection 進行處理,可能是因為這樣所以我問了幾位夥伴好像都不太常用。

Resource Collection 詳細可參考:https://ithelp.ithome.com.tw/articles/10333916

而如果前後端不分離的網站,就不會使用 Resource Collection,必須使用其他方法處理。

Accessor存取子 & Mutator更動子

https://ithelp.ithome.com.tw/upload/images/20231006/201628932w07L6SDDG.png

Laravel 8 以前的寫法

Laravel 在第九版時針對 Accessor & Mutator 寫法進行大改版,但是有相容舊的版本,所以也是可以用的

// Model 裡面加入
public function setFirstNameAttribute($value) 
{
	// function 命名為 get (Mutator) 或 set (Accessor) + table 欄位名稱改為小駝峰 + Attribute
	$this->attributes['first_name'] = strtolower($value);
}

Laravel 9 以後的寫法

Laravel 9 以後將 Mutator 及 Accessor 寫在一起,不用分開 function,可以更簡潔地表示。

Mutator 存入 Database 前先處理資料,轉換成指定的資料格式

protected function imagePath(): Attribute
{
    return Attribute::make(
		set: fn(string $value) => Storage::url($value),
    );
}
  • function 名稱以 table 欄位名稱,一樣要用小駝峰形式
  • function 的型別提示為 Illuminate\Database\Eloquent\Casts\Attribute
  • 每個 Mutator 和 Accessor 都要回傳 Attribute::make() 方法
  • Attribute::make() 裡面用 named argument 方式寫入,set 為 Mutator、get 為 Accessor
  • 最後可以用 arrow function 的方式寫入轉換方式
    (以上涉及 php 原生比較新的寫法 named arguments,感謝工作室 Louis 大大的解說,我幫各位貼上 好想夥伴 Lucas的說明,或可參考其鐵人賽文章~)

存入資料庫時,圖片路徑就已經加入了 Storage::url() 的效果

https://ithelp.ithome.com.tw/upload/images/20231006/20162893tHXshkMZI5.png

Accessor 從 Database 取出時才進行處理,轉換成指定資料格式

protected function imagePath(): Attribute
{
    return Attribute::make(
        get: fn(string $value) => 
            str_starts_with($value, 'http') ? $value : Storage::url($value),
		// 如果 image_path 欄位不是以 http 開頭的話,就讓值經過 Storage::url() 轉換
    );
}

Accessor 使用的方式跟 Mutator 相同,只有 named argument 方式改為 get

刻意將資料打出來看看

id = 36 的 image_path 欄位為圖片路徑、 id = 37 的 image_path 欄位為網址

https://ithelp.ithome.com.tw/upload/images/20231006/20162893iB2nuGCjtQ.png

使用 Accessor 後,id = 36 的 image_path 轉為 urI

https://ithelp.ithome.com.tw/upload/images/20231006/20162893VXj6jJaNJk.png

而原本 id = 37 的 image_path 為網址,使用後不改變

https://ithelp.ithome.com.tw/upload/images/20231006/20162893lw7ceuBUxR.png


上一篇
Laravel filesystem / 專案筆記:團購圖片上傳功能
下一篇
匯出加密的 PDF(1):wkhtmltopdf、laravel-snappy
系列文
Laravel 後端菜鳥可以知道的流程概念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言